import org.jlinalg.LinSysSolver;
import org.jlinalg.Matrix;
import org.jlinalg.Rational;
import org.jlinalg.FieldElement;
import org.jlinalg.Vector;

import java.util.*;
import java.io.*;
import java.math.BigInteger;

/**
 * Example that computes a solution of a linear equation system for the domain
 * of rational numbers.
 * 
 * @author Andreas Keilhauer, Georg Thimm
 */
public class Strip
{
        public static boolean DEBUG = false;

	/**
	 * start the demonstration
	 * 
	 * @param argv
	 *            is ignored
	 */
	public static void main(String[] argv)
	{
	String fileName = argv[0];
	String rows = argv[1];
	String cols = argv[2];
	String fvaName = argv[3];
	
	int r = Integer.parseInt(rows);
	int c = Integer.parseInt(cols);

	System.out.println("* Will assume that the file '"+fileName+"' contains "+r+" rows and "+c+" columns and FVA data is in file "+fvaName+".");
	System.out.println("* Will assume that the matrix is of the form a0 a1 a2... and becomes a1 + a2 + ... >= -a0");

	Rational[][] nums = new Rational[r][c];
	
	int at = 0;

                        try     {
                                FileReader fr = new FileReader(fileName);
                                BufferedReader br = new BufferedReader(fr);

                                String record = new String();
                                while((record=br.readLine()) != null)
                                        {
                                        if( record.startsWith("//") ) continue; //! ignore comments

                                        String[] tripData = record.split(" ");

					for( int x=0; x<c; x++ )
						{
						String numerator = null;
						String denominator = null;

						String ratString = tripData[x];

						int locbar = ratString.indexOf('/');
						if( locbar == -1 )
							{
							numerator = ratString;
							denominator = "1";
							}
						else
							{
							numerator = ratString.substring( 0, locbar );
							denominator = ratString.substring( locbar+1 );
							}

						// System.out.println("* Got rational ["+numerator+"]["+denominator+"]");

						BigInteger bnum = new BigInteger(numerator);
						BigInteger dnum = new BigInteger(denominator);

						nums[at][x] = new Rational(bnum, dnum);

						// System.out.print(" "+nums[at][x]+" ");

						}
					at++;
					// System.out.println();
					}

                                }
                        catch (IOException e)
                                {
                                // catch possible io errors from readLine()
                                System.out.println("Problem reading file "+fileName);
                                System.exit(0);
                                }

		int fvaSeen = 0;

		Rational fluxes[] = new Rational[c-1]; 
		boolean fixed[] = new boolean[c-1];
		int numFixed = 0;

		System.out.println("* Saw "+at+" rows.");

		System.out.println("* Now reading in the FVA data...");

                        try     {
                                FileReader fr = new FileReader(fvaName);
                                BufferedReader br = new BufferedReader(fr);

                                String record = new String();
                                while((record=br.readLine()) != null)
                                        {
                                        if( record.startsWith("//") ) continue; //! ignore comments

                                        String[] tripData = record.split(" ");

					System.out.print("* Processing '"+tripData[0]+"'");

					if( tripData[6].equals("FIXED") )
						{
						System.out.print(" -- fixed ");
						fixed[fvaSeen] = true;
						numFixed++;

                                                String numerator = null;
                                                String denominator = null;

                                                String ratString = tripData[2];

                                                int locbar = ratString.indexOf('/');
                                                if( locbar == -1 )
                                                        {
                                                        numerator = ratString;
                                                        denominator = "1";
                                                        }
                                                else
                                                    	{
                                                        numerator = ratString.substring( 0, locbar );
                                                        denominator = ratString.substring( locbar+1 );
                                                        }

                                                // System.out.println("["+numerator+"]["+denominator+"]");

                                                BigInteger bnum = new BigInteger(numerator);
                                                BigInteger dnum = new BigInteger(denominator);

                                                fluxes[fvaSeen] = new Rational(bnum, dnum);
						//! System.out.println(fluxes[fvaSeen].toString());

						}
					else	{
						System.out.println(" -- variable");
						}


					fvaSeen++;
					}

                                }
                        catch (IOException e)
                                {
                                // catch possible io errors from readLine()
                                System.out.println("Problem reading file "+fileName);
                                System.exit(0);
                                }

		System.out.println("* "+numFixed+" of fluxes are fixed.");

		int map = 0;
		for(int s=0;s<fluxes.length;s++)
			{
			if( fixed[s] == false )
				{
				map++;
				System.out.println("* x"+(s+1)+" will become x"+map);
				}
			}

		System.out.println("* Ok now going to subtract row for row the fixed columns.");

		System.out.println("* Here we go...");
		System.out.println("H-representation");
		System.out.println("begin");
		System.out.println(at+" "+(c-numFixed)+" rational"); 

		for(int row=0; row<at; row++ )
			{
			if( DEBUG ) System.out.println("* Row: "+(row+1));

			Rational rhs = nums[row][0].negate();

			if( DEBUG ) System.out.println("* Negated col 0 is "+rhs.toString());

			for(int col=1; col<c; col++)
				{
				if( DEBUG ) System.out.println("* Checking x"+col+"...");
				if( fixed[col-1] )
					{	
					if( DEBUG ) System.out.println("* x"+col+" was fixed, removing...");

					Rational m = nums[row][col];
					if( DEBUG ) System.out.println("* Matrix coeff: "+m.toString());

					Rational n = fluxes[col-1];
					if( DEBUG ) System.out.println("* Fixed flux: "+n.toString());

					Rational myprod = m.multiply(n);

					myprod = myprod.negate();

					if( DEBUG ) System.out.println("* Negative prod: "+myprod.toString());

					rhs = rhs.add(myprod);

					if( DEBUG ) System.out.println("* a0 after adding negprod: "+rhs.toString());
					}
				}

			rhs = rhs.negate();
			System.out.print(rhs.toString());

			for(int scan=0; scan<fixed.length; scan++)
				{
				if( !fixed[scan] )
					{
					System.out.print(" "+nums[row][scan+1]);
					}
				}
			System.out.println();
			}


		System.out.println("end");

	}
}

